
import { GameEvent } from "../config/EventConfig";
import EventManager from "../manager/EventManager";
import { AStar } from "./findpath/AStar";
import { GridMap } from "./findpath/Grid";
import Unit from "./Unit";

/**
 * 战斗组
 */
export class Group {
    /**
     * 战斗组ID
     */
    public groupId: number;
    /**
     * 是否失败
     */
    public isFaild: boolean = false;
    /**
     * 小兵
     */
    public units: Array<Unit> = new Array<Unit>();
    /**
     * 添加小兵
     * @param unit 
     */
    public add(unit: Unit) {
        unit.groupId = this.groupId;
        this.units.push(unit);
    }
    /**
     * 删除小兵
     * @param unit 
     */
    public remove(unit: Unit){
        for (let index = 0; index < this.units.length; index++) {
            const element = this.units[index];
            if (unit == element) {
                this.units.splice(index,1);
                return true;
            }
        }
        return false;
    }
    
}
/**
 * 游戏世界
 */
export default class GameWorld {
    /**
     * 战斗节点
     */
    public mapNode: cc.Node;
    /**
     * 网格边缘
     */
    public gridEdge: number = 38;
    /**
     * 自己战斗组ID
     */
    public selfGroupId: number;
    
    private groups: Array<Group> = new Array<Group>();
    /**
     * 所有小兵
     */
    allUnits: Set<Unit> = new Set<Unit>();
    /**
     * 是否结束
     */
    private isEnd = false;
    /**
     * 战败组的数量
     */
    private failds = 0;

    /**
     * 创建
     * @param selfGroup 我方战斗组数据
     * @param otherGroup 地方战斗组数据
     * @param node 战斗节点
     */
    public static create(selfGroup:Array<any>,otherGroup:Array<any>,node:cc.Node) {
        
        let world = new GameWorld();
        world.gridEdge = GridMap.instance.gridEdge;
        world.mapNode = node;
        let group = new Group();
        group.groupId = 0;
        world.addGroup(group);
        let group1 = new Group();
        world.addGroup(group1);
        group1.groupId = 1;
        world.selfGroupId = group.groupId;
        for (let i = 0; i < selfGroup.length; i++) {
            for (let j = 0; j < selfGroup[0].length; j++) {
                const unitId = selfGroup[i][j];
                const unitId1 = otherGroup[i][j];
                if (unitId) {
                    let unit = Unit.creat(unitId, group.groupId, world, cc.v2(i, j), cc.v2(0, 1));
                    world.addUnit(unit);
                }
                if (unitId1) {
                    let unit1 = Unit.creat(unitId1, group1.groupId, world, cc.v2(GridMap.instance.numCols-1-i, GridMap.instance.numRows-1-j), cc.v2(0, -1));
                    world.addUnit(unit1);
                }
            }
            
        }
        return world;
    }
    /**
     * 获取攻击范围内的目标
     * @param unit 
     */
    public getInAttack(unit: Unit): Unit {
        let distance = 0;
        let attackDistance = unit.getProperty('atk_range');
        let aimUnit = null;
        for (let i = 0; i < this.groups.length; i++) {
            const group = this.groups[i];
            if (group.groupId != unit.groupId) {
                for (let index = 0; index < group.units.length; index++) {
                    const u = group.units[index];
                    if (!u.isDeath()) {
                        let d = (u.gridPos.x - unit.gridPos.x) * (u.gridPos.x - unit.gridPos.x) + (u.gridPos.y - unit.gridPos.y) * (u.gridPos.y - unit.gridPos.x);
                        if (d < attackDistance * attackDistance) {
                            return u;
                        }
                        if (distance == 0 || d < distance) {
                            distance = d;
                            aimUnit = u;
                        }
                    }
                }
            }
        }
        return aimUnit;
    }
    /**
     * 获取最近的小兵
     * @param unit 
     */
    public getNearestUnit(unit: Unit): Unit {
        let distance = 0;
        let aimUnit = null;
        this.groups.forEach((group) => {
            if (group.groupId != unit.groupId) {
                group.units.forEach((u) => {
                    if (!u.isDeath()) {
                        let d = (u.gridPos.x - unit.gridPos.x) * (u.gridPos.x - unit.gridPos.x) + (u.gridPos.y - unit.gridPos.y) * (u.gridPos.y - unit.gridPos.x);
                        if (distance == 0 || d < distance) {
                            distance = d;
                            aimUnit = u;
                        }
                    }
                })
            }
        });
        return aimUnit;
    }
    /**
     * 添加战斗组
     * @param group 
     */
    public addGroup(group: Group) {
        this.groups.push(group);
    }
    /**
     * 添加小兵至指定的组
     * @param unit 小兵
     * @param groupId 战斗组ID
     */
    public addUnitToGroup(unit: Unit, groupId: number) {
        this.groups.forEach((group) => {
            if (group.groupId == groupId) {
                unit.groupId = groupId;
                unit.world = this;
                group.add(unit);
            }
        })
    }
    /**
     * 获取指定战斗组数据
     * @param groupId 战斗组ID
     */
    public getGroup(groupId: number): Group {
        let g = null;
        this.groups.forEach((group) => {
            if (group.groupId == groupId) {
                g = group;
            }
        });
        return g;
    }
    /**
     * 添加小兵
     * @param unit 小兵
     */
    public addUnit(unit: Unit) {
        let group = this.getGroup(unit.groupId);
        this.allUnits.add(unit);
        group.add(unit);
    }
    /**
     * 移除小兵
     * @param unit 
     */
    public removeUint(unit: Unit) {
        let group = this.getGroup(unit.groupId);
        this.allUnits.delete(unit);
        group.remove(unit);
    }

    /**
     * 游戏结束
     */
    public gameOver() {
        if (this.isEnd) {
            return;
        }
        for (let index = 0; index < this.groups.length; index++) {
            const group = this.groups[index];
            if (!group.isFaild) {
                console.log('win', group.groupId);
                EventManager.instance.emit(GameEvent.GAMEOVER,group.groupId);
                return;
            }
        }
    }
    /**
     * 游戏世界update心跳
     * @param dt 
     */
    public update(dt) {
        AStar.instance.update();
        this.failds = 0;
        let length = this.groups.length;
        for (let index = 0; index < length; index++) {
            const group = this.groups[index];
            // console.log(group.units);
            
            if (group.units.length == 0) {
                group.isFaild = true;
                ++this.failds;
                if (this.failds == length - 1) {
                    this.gameOver();
                    this.isEnd = true;
                }
            }
        }
        this.allUnits.forEach((unit) => {
            unit.update(dt);
        })
    }
}